package com.dc.project.util;

import com.dc.project.constant.ConstantCommon;
import com.dc.project.entity.po.Task;
import com.dc.project.entity.po.TaskFileCommit;
import com.dc.project.entity.vo.TaskFileCommitVo;
import com.dc.project.service.TaskFileCommitService;
import com.dc.project.service.TaskService;
import com.dc.project.util.reader.ReadUtil;
import com.dc.project.util.reader.base.FileReaderModel;
import com.own.component.common.base.AbstractAtomicQueueService;
import com.own.component.common.model.R;
import com.own.util.FileUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.ArrayList;

/**
 * TaskCommitResolveUtil
 *
 * @author chenxueli
 * @date 2025-03-11 09:53:26
 */
@Slf4j
@Component
public class TaskCommitResolveUtil extends AbstractAtomicQueueService {

    /**
     * 内容提取的系统提示
     */
    private static final String SYSTEM_PROMPT = """
            # 角色
            你是一个专业的文本精简压缩助手，你将根据客户的文本需求，根据以下规则一步步执行任务。
            # 任务描述与要求
            1. 逐句分析输入文本，精准提炼每句话中的核心要点，保证核心含义完整保留。
            2. 全面排查文本中存在的重复词汇、短语以及表述，将其去除，避免内容冗余。
            3. 对精简后的文本进行整体逻辑梳理，确保原文所表达的主旨、关键信息以及逻辑关系毫无改变，语句流畅自然。
            # 参考示例
            示例 1：
            用户：苹果是一种非常好吃的水果，苹果富含维生素，苹果还很有营养。
            输出：苹果是一种好吃且富含维生素、很有营养的水果。
            示例 2：
            用户：小明今天去了公园，小明在公园里面玩耍，小明玩得很开心。
            输出：小明今天去公园玩耍，玩得很开心。
            示例 3：
            用户：这本书的内容十分精彩，这本书的情节特别吸引人，这本书非常值得一读。
            输出：这本书内容精彩、情节吸引人，非常值得一读。
            # 相关限制
            1. 核心信息界定需准确，必须完整保留原文的核心要点，严禁随意增减关键内容。
            2. 重复内容判断要谨慎，去除重复内容时，要仔细甄别，不能误删必要信息。
            3. 语言表达要规范，精简后的文本应语句通顺、表意明确，符合正常的语言表达习惯 。
            4. 不得改变原文逻辑关系，无论句子结构如何调整，都要保证原文逻辑连贯。
            """;

    @Resource
    private TaskFileCommitService taskFileCommitService;
    @Resource
    private TaskService taskService;

    @Resource
    private TaskSseEmitterUtil taskSseEmitterUtil;
    @Resource
    private VolcengineChatUtil volcengineChatUtil;

    /**
     * 单条信息的处理
     *
     * @return 是否需要继续执行
     */
    @Override
    protected boolean invoke() {
        // 获取第一条未处理的数据
        var commit = taskFileCommitService.getFirstNotCompleteDetail();
        if (commit == null) {
            return false;
        }
        var commitId = commit.getId();
        // 同步任务状态到前端
        send(commit, TaskFileCommit.Status.PARSING);
        // 删除已有的子信息
        taskFileCommitService.deleteByParentCommitId(commitId);
        // 获取任务信息
        var task = taskService.getPoById(commit.getFkTaskId(), false);
        if (task == null) {
            // 任务失败
            send(commit, TaskFileCommit.Status.PROCESS_FAILED);
            return true;
        }
        // 利用工具读取文件中的文本内容（不使用大模型）
        var model = ReadUtil.read(commit.getFilePath());
        // 如果文件列表有值，需要执行文件上传
        taskFileCommitService.putSubFileList(commit, model.getSubFileList());
        // 获取到文件内容
        var content = model.getContent();
        // 如果没有内容默认为解析失败
        if (StringUtils.isBlank(content)) {
            send(commit, TaskFileCommit.Status.PROCESSED);
            return true;
        }
        // 保存解析的文本内容
        taskFileCommitService.updateParseMessage(commitId, content);
        commit.setParseMessage(content);
        // 对文本内容进行提炼，防止文本过长，或者有重复的数据
        compressing(task, commit);
        // 如果包含有父提交的信息，需要去查询所有的子提交是否完成
        aFreshResolveParent(task, commit.getFkParentCommitId());
        return true;
    }

    /**
     * 对文本内容进行提炼，防止文本过长，或者有重复的数据
     *
     * @param task   任务信息
     * @param commit 提交记录
     */
    private void compressing(Task task, TaskFileCommit commit) {
        // 对文本内容进行提炼，防止文本过长，或者有重复的数据
        send(commit, TaskFileCommit.Status.COMPRESSING);
        var content = commit.getParseMessage();
        var fileExtension = FileUtil.getSuffix(commit.getFilePath());
        var userPromptList = new ArrayList<String>();
        if (fileExtension.contains("xls")) {
            userPromptList.add("Excel文件，不需要去删减单元格内容，只需要去除空的sheet页。");
        }
        userPromptList.add(
                "我们的公司名称是：" + task.getCompanyName() + "，需要通过分析文本内容，判断是否属于我公司，如果必定不是我公司的直接返回给我空文本。"
        );
        userPromptList.add("以下是需要精炼的文本内容：" + content);
        // 调用ai大模型压缩文本内容
        content = volcengineChatUtil.invoke(SYSTEM_PROMPT, userPromptList);
        // 如果没有内容默认为解析失败
        if (StringUtils.isBlank(content)) {
            send(commit, TaskFileCommit.Status.COMPRESS_FAILED);
            return;
        }
        // 保存压缩后的文本内容
        taskFileCommitService.updateCompressMessage(commit.getId(), content);
        send(commit, TaskFileCommit.Status.PROCESSED);
    }

    /**
     * 发送消息
     *
     * @param commit 提交记录
     * @param status 状态
     */
    private void send(TaskFileCommit commit, int status) {
        taskFileCommitService.updateStatus(commit.getId(), status);
        commit.setStatus(status);
        taskSseEmitterUtil.send(
                commit.getFkTaskId(),
                ConstantCommon.SSE_EVENT.COMMIT_PARSE_STATUS,
                () -> R.success(new TaskFileCommitVo(commit))
        );
    }

    /**
     * 重新处理父信息
     *
     * @param task           任务信息
     * @param parentCommitId 父提交记录id
     */
    private void aFreshResolveParent(Task task, Long parentCommitId) {
        // 如果包含有父提交的信息，需要去查询所有的子提交是否完成
        if (parentCommitId != null) {
            var complete = taskFileCommitService.checkSubComplete(parentCommitId);
            if (complete) {
                // 查询出父一级的信息
                var parentCommit = taskFileCommitService.getPoById(parentCommitId, false);
                if (parentCommit == null) {
                    return;
                }
                // 查询出所有的子提交信息
                var subCommitList = taskFileCommitService.listByParentCommitId(parentCommitId);
                var parseMessage = parentCommit.getParseMessage();
                // 进行数据合并
                for (int i = 0; i < subCommitList.size(); i++) {
                    var subCommit = subCommitList.get(i);
                    // 进行数据替换
                    parseMessage = FileReaderModel.replacePlaceholder(i, parseMessage, subCommit.getParseMessage());
                }
                parentCommit.setParseMessage(parseMessage);
                taskFileCommitService.update(parentCommit);
                compressing(task, parentCommit);
            }
        }
    }

}
